package cc.spider.core.thread;

import cc.spider.exception.ThreadPoolException;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public abstract class AbsThreadTool implements IThreadPool {
    protected ThreadPoolExecutor executorService;
    /**
     * 线程池处理任务的最大线程数
     */
    protected int maxThreadCount;
    /**
     * 工作队列最大容量值
     */
    protected int maxWorkQueueCapacity;

    /**
     * 默认线程池数量
     */
    protected static final int default_thread_count = 3;

    /**
     * 默认工作队列的最大容量
     */
    protected static final int default_work_queue_capacity = 100;

    /**
     * 活跃中的任务数量
     */
    private AtomicInteger workingCount = new AtomicInteger(0);


    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public AbsThreadTool() {
        this(default_thread_count, default_work_queue_capacity);
    }

    public AbsThreadTool(int maxThreadCount, int maxWorkQueueCapacity) {
        this.maxThreadCount = maxThreadCount;
        this.maxWorkQueueCapacity = maxWorkQueueCapacity;
        if (maxWorkQueueCapacity > Integer.MAX_VALUE - maxThreadCount) {
            throw new ThreadPoolException("maxWorkQueueCapacity的值不得大于Integer.MAX_VALUE - maxThreadCount");
        }
        this.executorService = new ThreadPoolExecutor(maxThreadCount, maxThreadCount, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(maxWorkQueueCapacity + maxThreadCount), (r, executor) -> {
            System.err.println("超标" + executor.getQueue().size() + "<" + workingCount.get());
            System.exit(0);
        });
    }

    public AbsThreadTool(ThreadPoolExecutor executorService) {
        if (executorService == null) {
            throw new ThreadPoolException("executorService不能为null");
        }
        this.maxThreadCount = executorService.getMaximumPoolSize();
        this.maxWorkQueueCapacity = executorService.getQueue().size();
        if (maxWorkQueueCapacity > Integer.MAX_VALUE - maxThreadCount) {
            throw new ThreadPoolException("maxWorkQueueCapacity的值不得大于Integer.MAX_VALUE - maxThreadCount");
        }
        this.executorService = executorService;
    }

    @Override
    public void addTask(Runnable task) {
        if (workingCount.get() >= maxWorkQueueCapacity) {
            try {
                lock.lock();
                while (workingCount.get() >= maxWorkQueueCapacity) {
                    condition.await();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
        workingCount.incrementAndGet();
        executorService.execute(() -> {
            try {
                task.run();
            } finally {
                try {
                    lock.lock();
                    workingCount.decrementAndGet();
                    condition.signal();
                } finally {
                    if (lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }

            }
        });
    }

    public BlockingQueue<Runnable> getQueue() {
        return executorService.getQueue();
    }

    @Override
    public ExecutorService getThreadPool() {
        return executorService;
    }
}
